package com.meiyuetao.myt.sale.service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

import lab.s2jh.auth.entity.Department;
import lab.s2jh.auth.security.AuthUserHolder;
import lab.s2jh.auth.service.DepartmentService;
import lab.s2jh.bpm.service.ActivitiService;
import lab.s2jh.core.dao.BaseDao;
import lab.s2jh.core.security.AuthContextHolder;
import lab.s2jh.core.service.BaseService;
import lab.s2jh.core.util.DateUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.Lists;
import com.meiyuetao.myt.core.constant.VoucherStateEnum;
import com.meiyuetao.myt.core.constant.VoucherTypeEnum;
import com.meiyuetao.myt.core.service.VoucherNumGenerateService;
import com.meiyuetao.myt.finance.dao.BizTradeUnitDao;
import com.meiyuetao.myt.finance.entity.BizTradeUnit;
import com.meiyuetao.myt.finance.entity.TradeReceipt;
import com.meiyuetao.myt.finance.entity.TradeReceiptDetail;
import com.meiyuetao.myt.finance.service.TradeReceiptService;
import com.meiyuetao.myt.md.dao.CommodityDao;
import com.meiyuetao.myt.sale.dao.SaleReturnApplyDao;
import com.meiyuetao.myt.sale.dao.SaleReturnDao;
import com.meiyuetao.myt.sale.entity.BoxOrderDetailCommodity;
import com.meiyuetao.myt.sale.entity.SaleReturn;
import com.meiyuetao.myt.sale.entity.SaleReturnApply;
import com.meiyuetao.myt.sale.entity.SaleReturnApply.LastAuditResultEnum;
import com.meiyuetao.myt.sale.entity.SaleReturnApplyHistory;
import com.meiyuetao.myt.sale.entity.SaleReturnApplyHistory.ReturnApplyStatusEnum;
import com.meiyuetao.myt.sale.entity.SaleReturnDetail;
import com.meiyuetao.myt.stock.dao.StorageLocationDao;
import com.meiyuetao.myt.stock.entity.CommodityStock;
import com.meiyuetao.myt.stock.entity.StockInOut;
import com.meiyuetao.myt.stock.service.CommodityStockService;
import com.meiyuetao.myt.stock.service.StockInOutService;

@Service
@Transactional
public class SaleReturnApplyService extends BaseService<SaleReturnApply, Long> {

    @Autowired
    private SaleReturnApplyDao saleReturnApplyDao;

    @Autowired
    private SaleReturnDao saleReturnDao;

    @Autowired
    private SaleReturnService saleReturnService;

    @Autowired
    private CommodityDao commodityDao;

    @Autowired
    private StorageLocationDao storageLocationDao;

    @Autowired
    private CommodityStockService commodityStockService;

    @Autowired
    private StockInOutService stockInOutService;

    @Autowired
    private ActivitiService activitiService;

    @Autowired
    private VoucherNumGenerateService voucherNumGenerateService;

    @Autowired
    private SaleReturnApplyHistoryService saleReturnApplyHistoryService;

    @Autowired
    private TradeReceiptService tradeReceiptService;

    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private BizTradeUnitDao bizTradeUnitDao;

    @Override
    protected BaseDao<SaleReturnApply, Long> getEntityDao() {
        return saleReturnApplyDao;
    }

    public void bpmCreate(SaleReturnApply entity, Map<String, Object> variables) {
        entity.setVoucher(voucherNumGenerateService.getVoucherNumByType(VoucherTypeEnum.THSQ));
        saleReturnApplyDao.save(entity);
        activitiService.startProcessInstanceByKey("BPM_SALE_RETURN_APPLY", entity);
    }

    public void bpmUpdate(SaleReturnApply entity, String taskId, Map<String, Object> variables) {
        saleReturnApplyDao.save(entity);
        activitiService.completeTask(taskId, variables);
    }

    public void inStore(SaleReturnApply bindingEntity, String commodityStoreId) {
        SaleReturn entity = new SaleReturn();
        entity.setVoucher(voucherNumGenerateService.getVoucherNumByType(VoucherTypeEnum.TH));
        entity.setReferenceVoucher(bindingEntity.getVoucher());
        entity.setCustomerProfile(bindingEntity.getCustomerProfile());
        entity.setReferenceSource("美月淘");
        entity.setLastOperationSummary(entity.buildLastOperationSummary("退货入库"));
        entity.setMemo("退货申请单 商品入库");
        entity.setVoucherDate(new Date());
        // entity.setAuditDate(new Date());
        entity.setLastOperationSummary(entity.buildLastOperationSummary("基于退货申请自动创建退货单"));

        // 收货人信息
        entity.setReceivePerson(bindingEntity.getSaleReturnName());
        entity.setDeliveryAddr(bindingEntity.getSaleReturnDetailAddr());
        entity.setMobilePhone(bindingEntity.getSaleReturnPhone());

        CommodityStock commodityStock = commodityStockService.findOne(Long.parseLong(commodityStoreId));
        BoxOrderDetailCommodity boxOrderDetailCommodity = bindingEntity.getBoxOrderDetailCommodity();
        List<SaleReturnDetail> saleReturnDetails = Lists.newArrayList();
        SaleReturnDetail saleReturnDetail = new SaleReturnDetail();
        saleReturnDetail.setSaleReturn(entity);
        saleReturnDetail.setCommodity(commodityStock.getCommodity());
        saleReturnDetail.setStorageLocation(commodityStock.getStorageLocation());
        saleReturnDetail.setBatchNo(commodityStock.getBatchNo());
        saleReturnDetail.setQuantity(bindingEntity.getQuantity());
        saleReturnDetail.setPrice(boxOrderDetailCommodity.getPrice());
        saleReturnDetail.setOriginalAmount(boxOrderDetailCommodity.getOriginalAmount());
        saleReturnDetail.setDiscountAmount(boxOrderDetailCommodity.getDiscountAmount());
        saleReturnDetail.setCommodityAmount(boxOrderDetailCommodity.getCommodityAmount());
        saleReturnDetail.setScrapped(false);
        saleReturnDetail.setCostAmount(boxOrderDetailCommodity.getCostAmount());

        saleReturnDetails.add(saleReturnDetail);
        entity.setSaleReturnDetails(saleReturnDetails);

        Department department = AuthUserHolder.getLogonUser().getDepartment();
        if (department == null) {
            department = departmentService.findByProperty("code", "MGMT");
        }
        entity.setVoucherDepartment(department);
        entity.setVoucherUser(AuthUserHolder.getLogonUser());

        entity.setVoucherState(VoucherStateEnum.POST);
        StockInOut stockInOut = buildDefaultStockInOut(entity, bindingEntity.getBoxOrderDetailCommodity(), commodityStoreId);
        stockInOut.setDiffQuantity(bindingEntity.getQuantity());
        stockInOut.setOperationSummary("退货申请 商品入库（" + bindingEntity.getVoucher() + "）");
        stockInOut.setDiffStockAmount(commodityStock.getCostPrice().multiply(bindingEntity.getQuantity()));
        stockInOut.setOperationSummary("退货入库");
        stockInOutService.saveCascade(stockInOut);
        saleReturnDao.save(entity);
    }

    private StockInOut buildDefaultStockInOut(SaleReturn saleReturn, BoxOrderDetailCommodity bodc, String commodityStoreId) {
        CommodityStock commodityStock = commodityStockService.findOne(Long.parseLong(commodityStoreId));
        StockInOut stockInOut = new StockInOut(saleReturn.getVoucher(), bodc.getSubVoucher(), VoucherTypeEnum.TH, commodityStock);
        return stockInOut;
    }

    private void createHistory(SaleReturnApply bindingEntity, ReturnApplyStatusEnum status, String processComment) {
        SaleReturnApplyHistory history = new SaleReturnApplyHistory();
        history.setSaleReturnApply(bindingEntity);
        history.setVersion(0);
        history.setOperater(AuthContextHolder.getAuthUserPin());
        history.setProcessTime(DateUtils.formatDateNow());
        history.setApplyHistoryStatus(status);
        history.setProcessComment(processComment);
        history.setProcessResult(bindingEntity.getProcessResult());
        saleReturnApplyHistoryService.save(history);
    }

    public void bpmPostAudit(SaleReturnApply bindingEntity, String taskId, Map<String, Object> variables) {
        this.bpmUpdate(bindingEntity, taskId, variables);
        createHistory(bindingEntity, ReturnApplyStatusEnum.POST, "提交审核完成");// 记录
    }

    public void bpmStoreReceive(SaleReturnApply bindingEntity, String taskId, Map<String, Object> variables) {
        this.bpmUpdate(bindingEntity, taskId, variables);
        createHistory(bindingEntity, ReturnApplyStatusEnum.S_RECEIPT, "库房收货完成");// 记录
    }

    public void bpmSaleReturnAudit(SaleReturnApply bindingEntity, String taskId, Map<String, Object> variables) {
        this.bpmUpdate(bindingEntity, taskId, variables);
        if (bindingEntity.getLastAuditResult().equals(LastAuditResultEnum.EXCHANGE)) {
            SaleReturn saleReturn = saleReturnService.findByProperty("referenceVoucher", bindingEntity.getVoucher());
            saleReturn.setAuditDate(new Date());// 设置了审核时间，就可以显示在销售单的 从退换货单选取
            saleReturn.setLastOperationSummary(saleReturn.buildLastOperationSummary("退货申请，退换货审核通过"));
            saleReturn.setMemo("退货申请，退换货审核通过, 审核结果[退货]");
            saleReturnDao.save(saleReturn);
        }
        createHistory(bindingEntity, ReturnApplyStatusEnum.AUDIT, "退换货审核完成");// 记录
    }

    public void bpmRefundment(SaleReturnApply entity, String taskId, Map<String, Object> variables, List<TradeReceiptDetail> tradeReceiptDetails) {

        // 创建付款单
        TradeReceipt tradeReceipt = new TradeReceipt();
        tradeReceipt.setVoucher(voucherNumGenerateService.getVoucherNumByType(VoucherTypeEnum.FKD));
        tradeReceipt.setVoucherDate(new Date());
        tradeReceipt.setVoucherUser(AuthUserHolder.getLogonUser());
        Department department = AuthUserHolder.getLogonUser().getDepartment();
        if (department == null) {
            department = departmentService.findByProperty("code", "MGMT");
        }
        tradeReceipt.setVoucherDepartment(department);
        BizTradeUnit bizTradeUnit = bizTradeUnitDao.findOne(entity.getCustomerProfile().getBizTradeUnitId());
        tradeReceipt.setBizTradeUnit(bizTradeUnit);
        tradeReceipt.setBizVoucher(entity.getVoucher());
        tradeReceipt.setBizVoucherType(VoucherTypeEnum.THSQ);
        tradeReceipt.setReferenceVoucher(entity.getVoucher());
        tradeReceipt.setReceiptType(VoucherTypeEnum.FKD);
        tradeReceipt.setPayTime(new Date());
        tradeReceipt.setVoucherState(VoucherStateEnum.POST);
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (TradeReceiptDetail tradeReceiptDetail : tradeReceiptDetails) {
            tradeReceiptDetail.setTradeReceipt(tradeReceipt);
            tradeReceiptDetail.setPayTime(new Date());
            totalAmount = totalAmount.add(tradeReceiptDetail.getAmount());
            tradeReceipt.addTradeReceiptDetail(tradeReceiptDetail);
        }
        tradeReceipt.setTotalAmount(totalAmount);
        tradeReceipt.setAccountSubject(entity.getAccountSubject());
        tradeReceiptService.create(tradeReceipt);
        this.bpmUpdate(entity, taskId, variables);
        createHistory(entity, ReturnApplyStatusEnum.REFUND, "退款完成");// 记录
    }
}
